/*
 * Instruction.java
 * Copyright (C) 05/21/2010, Lhrod
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 */
package Sindarin.Common;

/**
 *
 * @author Lhrod
 */
public class Instruction implements java.io.Serializable {

    public enum Opcode {
        LOADC, LOAD, STORE, INC, DEC, DUP, MULC, JUMP, JUMPZ, WAIT
        , EXIT, POP, IODELAY, LOADDELAY, CMP, ALU, CALLSUB, RETURN, LOADNATIVEMODE, PRINT, LOADDATE, LOADTIME, BEEP, GETCOMPONENT

        , MOUSECLICK, MOUSEDCLICK, KEY, TEXT
        , MOUSEMOVE, MOUSEPRESS, MOUSERELEASE, KEYPRESS, KEYRELEASE, GETCOLOR
    }

    public enum Operator {
        LOCATION, MACROKEY, MYCOLOR, INTEGER, NUMBER, STRING, EMPTY
    }
    public Opcode opcode;
    public Object operator;

    /** Creates a new instance of Instruction */
    public Instruction(Opcode opcode, Object operador) {
        this.opcode = opcode;
        this.operator = operador;
    }

    @Override
    public String toString() {
        return "Opcode: " + opcode.name() + ", operator: " + operator;
    }

    /*public static Integer[] inst2IntArr(Instruction inst) {
        Vector res = new Vector();
        res.add(new Integer(inst.opcode.ordinal()));
        if (inst.operator == null) {
            res.add(new Integer(Operator.EMPTY.ordinal()));
            res.add(0);
        } else {
            String operName = inst.operator.getClass().getCanonicalName().toLowerCase();
            int lastDot = operName.lastIndexOf(".") + 1;
            operName = operName.substring(lastDot);
            Operator opType = Operator.valueOf(operName.toUpperCase());
            res.add(new Integer(opType.ordinal()));
            switch (opType) {
                case LOCATION:
                    Location l = (Location) inst.operator;
                    res.add(2);
                    res.add(new Integer(l.x));
                    res.add(new Integer(l.y));
                    break;
                case MACROKEY:
                    MacroKey k = (MacroKey) inst.operator;
                    int[] aK = k.getAllKey();
                    res.add(new Integer(aK.length));
                    for (int i : aK) {
                        res.add(new Integer(i));
                    }
                    break;
                case MYCOLOR:
                    MyColor c = (MyColor) inst.operator;
                    res.add(3);
                    res.add(new Integer(c.color.getRed()));
                    res.add(new Integer(c.color.getGreen()));
                    res.add(new Integer(c.color.getBlue()));
                    break;
                case INTEGER:
                case NUMBER:
                    int i = (Integer) inst.operator;
                    res.add(1);
                    res.add(new Integer(i));
                    break;
                case STRING:
                    String s = (String) inst.operator;
                    char[] aC = s.toCharArray();
                    res.add(aC.length);
                    for (int ch : aC) {
                        res.add(ch);
                    }
                    break;
            }
        }
        return (Integer[]) res.toArray(new Integer[]{});
    }

    public static Instruction intArr2Inst(Integer[] iA) {
        Vector tmp = new Vector();
        Opcode opc = Opcode.values()[iA[0]];
        Object oper = null;
        switch (Operator.values()[iA[1]]) {
            case LOCATION:
                oper = new Location(iA[3], iA[4]);
                break;
            case MACROKEY:
                for (int i = 3; i < iA[2] + 1; i++) {
                    tmp.add(new Integer(iA[i]));
                }
                oper = new MacroKey(tmp);
                break;
            case MYCOLOR:
                oper = new MyColor(iA[3], iA[4], iA[5]);
                break;
            case INTEGER:
            case NUMBER:
                oper = iA[3];
                break;
            case STRING:
                String sTmp = "";
                for (int i = 3; i < iA[2] + 3; i++) {
                    sTmp += (char) iA[i].intValue();
                }
                oper = new String(sTmp);
                break;
            case EMPTY:
                break;
        }

        return new Instruction(opc, oper);
    }

    public static Integer[] vector2IntArray(Vector<Instruction> vInst) {
        Vector<Integer> res = new Vector();

        for (Instruction i : vInst) {
            for (Integer in : Instruction.inst2IntArr(i)) {
                res.add(in);
            }
        }

        return (Integer[]) res.toArray(new Integer[]{});
    }

    public static Vector<Instruction> intArray2Vector(Integer[] bInst) {
        Vector<Instruction> res = new Vector();
        Integer[] tmp = new Integer[bInst.length];
        for (int i = 0; i < bInst.length; i += 3) {
            System.arraycopy(bInst, i, tmp, 0, bInst.length - i);
            Instruction inst = Instruction.intArr2Inst(tmp);
            res.add(inst);
            i += bInst[i + 2];
        }
        return res;
    }*/
}
